# File: Menu.py
# Copyright 2010 
# Author: Andrew Dorrycott
# License: GNU Lesser General Public License
# Original Repository: http://code.google.com/p/bobthezombie/

import sys
import pygame
import random
import datetime
import math

from Standard import *

class Menu():
    def __init__(self, engine):
        self.engine = engine
        self.Alive = True
        self.entered_tech_tree = False # default is false
        
        self.menu_set = None
        self.menus = {'in_game_menu': {'List': ['Continue', 'Save Game', 'Options', 'Quit to Main Menu', 'Exit Game'],
                                    'Title': "Bob the Zombie!",
                                    'Continue': {'method': self.SendKeyEvent, 'value': pygame.K_ESCAPE},
                                    'Save Game': {'method': self.ChangeMenu, 'value': 'in_game_save'},
                                    'Options' : {'method': self.ChangeMenu, 'value': 'in_game_options'},
                                    'Quit to Main Menu': {'method': self.engine.SendEvent, 'value': CustomEvents.quit_game},
                                    'Exit Game': {'method': self.engine.SendEvent, 'value': pygame.QUIT},
                                    },
                    
                    'in_game_options': {'List': ['Music', 'Sound', 'Controls', 'Back'],
                                        'Title': "Options",
                                        'Music': {'method': self.engine.ToggleMusic, 'value': None},
                                        'Sound': {'method': self.engine.ToggleSound, 'value': None},
                                        'Controls': {'method': self.ChangeMenu, 'value': 'in_game_controls'},
                                        'Back': {'method': self.ChangeMenu, 'value': 'in_game_menu'},
                        },
                    
                    'in_game_tech_tree': {'List': ['Stealth', 'Regeneration', 'Human Killing Machine', 'Zombie Army', 'Research Knowledge', 'Return to Game'],
                                        'Title': "Tech Tree",
                                        'Stealth': {'method': self.ChangeMenu, 'value': 'in_game_tech_tree_Stealth'},
                                        'Regeneration': {'method': self.ChangeMenu, 'value': 'in_game_tech_tree_Regeneration'},
                                        'Human Killing Machine': {'method': self.ChangeMenu, 'value': 'in_game_tech_tree_Human_Killing_Machine'},
                                        'Zombie Army': {'method': self.ChangeMenu, 'value': 'in_game_tech_tree_Zombie_Army'},
                                        'Research Knowledge': {'method': self.ChangeMenu, 'value': 'in_game_tech_tree_Research_Knowledge'},
                                        'Return to Game': {'method': self.SendKeyEvent, 'value': pygame.K_ESCAPE},
                        },
                    
                    'in_game_tech_tree_Stealth': {'List': ['Upgrade', 'Back'],
                                        'Title': "Stealth Tech Tree",
                                        'Upgrade': {'method': self.UpgradeSkill, 'value': 'Stealth'},
                                        'Back': {'method': self.ChangeMenu, 'value': 'in_game_tech_tree'},
                        },
                    
                    'in_game_tech_tree_Regeneration': {'List': ['Upgrade', 'Back'],
                                        'Title': "Regeneration Tech Tree",
                                        'Upgrade': {'method': self.UpgradeSkill, 'value': "Regeneration"},
                                        'Back': {'method': self.ChangeMenu, 'value': 'in_game_tech_tree'},
                        },
                    
                    'in_game_tech_tree_Human_Killing_Machine': {'List': ['Upgrade', 'Back'],
                                        'Title': "Human Killing Machine Tech Tree",
                                        'Upgrade': {'method': self.UpgradeSkill, 'value': "Human Killing Machine"},
                                        'Back': {'method': self.ChangeMenu, 'value': 'in_game_tech_tree'},
                        },
                    
                    'in_game_tech_tree_Zombie_Army': {'List': ['Upgrade', 'Back'],
                                        'Title': "Zombie Army Tech Tree",
                                        'Upgrade': {'method': self.UpgradeSkill, 'value': "Zombie Army"},
                                        'Back': {'method': self.ChangeMenu, 'value': 'in_game_tech_tree'},
                        },
                    
                    'in_game_tech_tree_Research_Knowledge': {'List': ['Upgrade', 'Back'],
                                        'Title': "Research Knowledge Tech Tree",
                                        'Upgrade': {'method': self.UpgradeSkill, 'value': "Research Knowledge"},
                                        'Back': {'method': self.ChangeMenu, 'value': 'in_game_tech_tree'},
                        },
                    
                    'in_game_controls': {'List': ['Up', 'Down', 'Left', 'Right', 'Fire', 'Use/Pickup', 'Open Tech Tree', 'Back'],
                                        'Title': "Controls",
                                        'Up': {'method': self.ChangeKey, 'value': 'Up'},
                                        'Down': {'method': self.ChangeKey, 'value': 'Down'},
                                        'Left': {'method': self.ChangeKey, 'value': 'Left'},
                                        'Right': {'method': self.ChangeKey, 'value': 'Right'},
                                        'Fire': {'method': self.ChangeKey, 'value': 'Fire'},
                                        'Use/Pickup': {'method': self.ChangeKey, 'value': 'Use/Pickup'},
                                        'Open Tech Tree': {'method': self.ChangeKey, 'value': 'Open Tech Tree'},
                                        'Back': {'method': self.ChangeMenu, 'value': 'in_game_options'},
                        },
                    
                    'in_game_save': {'List': ['Save 1', 'Save 2', 'Save 3', 'Save 4', 'Save 5', 'Back'],
                                        'Title': "Save Game",
                                        'Save 1': {'method': self.SaveGame, 'value': 1},
                                        'Save 2': {'method': self.SaveGame, 'value': 2},
                                        'Save 3': {'method': self.SaveGame, 'value': 3},
                                        'Save 4': {'method': self.SaveGame, 'value': 4},
                                        'Save 5': {'method': self.SaveGame, 'value': 5},
                                        'Back': {'method': self.ChangeMenu, 'value': 'in_game_menu'},
                        },
                    
                    'in_game_game_over': {'List': ['New Game', 'Back to Main Menu', 'Quit'],
                                        'Title': "Bob has Died!",
                                        'New Game': {'method': self.engine.SendEvent, 'value': CustomEvents.new_game},
                                        'Back to Main Menu': {'method': self.engine.SendEvent, 'value': CustomEvents.quit_game},
                                        'Quit': {'method': self.engine.SendEvent, 'value': pygame.QUIT},
                        },
                    
                    'in_game_victory_cure': {'List': ['New Game', 'Back to Main Menu', 'Quit'],
                                        'Title': "Bob was Cured!",
                                        'New Game': {'method': self.engine.SendEvent, 'value': CustomEvents.new_game},
                                        'Back to Main Menu': {'method': self.engine.SendEvent, 'value': CustomEvents.quit_game},
                                        'Quit': {'method': self.engine.SendEvent, 'value': pygame.QUIT},
                        },
                    
                    'in_game_victory_zombie_apocalypse': {'List': ['New Game', 'Back to Main Menu', 'Quit'],
                                        'Title': "Zombie Apocalypse!",
                                        'New Game': {'method': self.engine.SendEvent, 'value': CustomEvents.new_game},
                                        'Back to Main Menu': {'method': self.engine.SendEvent, 'value': CustomEvents.quit_game},
                                        'Quit': {'method': self.engine.SendEvent, 'value': pygame.QUIT},
                        },
                    
                    'in_game_victory_rampage': {'List': ['New Game', 'Back to Main Menu', 'Quit'],
                                        'Title': "Bob Rampage!",
                                        'New Game': {'method': self.engine.SendEvent, 'value': CustomEvents.new_game},
                                        'Back to Main Menu': {'method': self.engine.SendEvent, 'value': CustomEvents.quit_game},
                                        'Quit': {'method': self.engine.SendEvent, 'value': pygame.QUIT},
                        },
                    
                    'main_menu': {'List': ['New Game', 'Load Game', 'Options', 'Exit Game'],
                                    'Title': "Bob the Zombie!",
                                    'New Game': {'method': self.engine.SendEvent, 'value': CustomEvents.new_game},
                                    'Load Game': {'method': self.ChangeMenu, 'value': 'main_menu_load_game'},
                                    'Options' : {'method': self.ChangeMenu, 'value': 'main_menu_options'},
                                    'Exit Game': {'method': self.engine.SendEvent, 'value': pygame.QUIT},
                        },
                    
                    'main_menu_options': {'List': ['Music', 'Sound', 'Controls', 'Back'],
                                        'Title': "Options",
                                        'Music': {'method': self.engine.ToggleMusic, 'value': None},
                                        'Sound': {'method': self.engine.ToggleSound, 'value': None},
                                        'Controls': {'method': self.ChangeMenu, 'value': 'main_menu_controls'},
                                        'Back': {'method': self.ChangeMenu, 'value': 'main_menu'},
                        },
                    
                    'main_menu_controls': {'List': ['Up', 'Down', 'Left', 'Right', 'Fire', 'Use/Pickup', 'Open Tech Tree', 'Back'],
                                        'Title': "Controls",
                                        'Up': {'method': self.ChangeKey, 'value': 'Up'},
                                        'Down': {'method': self.ChangeKey, 'value': 'Down'},
                                        'Left': {'method': self.ChangeKey, 'value': 'Left'},
                                        'Right': {'method': self.ChangeKey, 'value': 'Right'},
                                        'Fire': {'method': self.ChangeKey, 'value': 'Fire'},
                                        'Use/Pickup': {'method': self.ChangeKey, 'value': 'Use/Pickup'},
                                        'Open Tech Tree': {'method': self.ChangeKey, 'value': 'Open Tech Tree'},
                                        'Back': {'method': self.ChangeMenu, 'value': 'main_menu_options'},
                        },
                    
                    'main_menu_load_game': {'List': ['Save 1', 'Save 2', 'Save 3', 'Save 4', 'Save 5', 'Back'],
                                        'Title': "Load Saved Game",
                                        'Save 1': {'method': self.LoadGame, 'value': 1},
                                        'Save 2': {'method': self.LoadGame, 'value': 2},
                                        'Save 3': {'method': self.LoadGame, 'value': 3},
                                        'Save 4': {'method': self.LoadGame, 'value': 4},
                                        'Save 5': {'method': self.LoadGame, 'value': 5},
                                        'Back': {'method': self.ChangeMenu, 'value': 'main_menu'},
                        },
                    
                    None: [None], # Default to prevent unforeseen errors
                    }
        
        self.currently_selected = None
        
        self.menu_background_border = pygame.image.load(IMAGES_MENU_BACKGROUND_BORDER)
        self.menu_background_inner = pygame.image.load(IMAGES_MENU_BACKGROUND_INNER)
        
        self.menu_background_border = pygame.transform.scale(self.menu_background_border,
                                                        (int( self.menu_background_border.get_size()[0] * 2 ),
                                                         int( self.menu_background_border.get_size()[1] * 4 )))
        
        self.menu_background_inner = pygame.transform.scale(self.menu_background_inner,
                                                       (int( self.menu_background_inner.get_size()[0] * 2 ),
                                                        int( self.menu_background_inner.get_size()[1] * 4 )))
        
        self.menu_background_border_rect = self.menu_background_border.get_rect()
        self.menu_background_inner_rect = self.menu_background_inner.get_rect()
        
        center_x = (self.engine.width / 2.0) - (self.menu_background_border_rect.width / 2.0)
        center_y = (self.engine.height / 2.0) - (self.menu_background_border_rect.height / 2.0)
        
        self.menu_background_border_rect.x = center_x
        self.menu_background_border_rect.y = center_y
        
        self.menu_background_inner_rect.x = center_x
        self.menu_background_inner_rect.y = center_y
        
        self.menu_background_inner.set_alpha(200)
    
    def SaveGame(self, play_number):
        self.engine.SaveGame(play_number)
        self.Alive = False
        self.SendKeyEvent(pygame.QUIT)
    
    def LoadGame(self, play_number):
        self.engine.LoadGame(play_number)
        self.Alive = False
    
    def UpgradeSkill(self, skill):
        self.engine.UpgradeSkill(skill)
    
    def ChangeKey(self, key):
        # If the menu set is for in_game then have the engine redraw the world behind the menu
        self.engine.ChangeKey(key, draw_game = self.menu_set.startswith("in_game"))
    
    def SendKeyEvent(self, type):
        # Send keydown event for any key
        self.engine.SendEvent(pygame.KEYDOWN, key = type)
    
    def Run(self, menu_set = None, entered_tech_tree = False):
        self.entered_tech_tree = entered_tech_tree
        self.currently_selected = self.menus[menu_set]['List'][0] # The first element should be selected by default
        self.menu_set = menu_set
        
        while self.Alive:
            
            self.Redraw( )
            self.OnEvent( pygame.event.get() )
        
        self.Alive = True # Once closed we need to be able to open it again
        
        return
    
    def Redraw(self):
        if self.menu_set.startswith('in_game'):
            self.engine.Redraw(flip = False) # Keep background but bring forward the menu
        else:
            self.engine.screen.fill( (0, 0, 0) ) # Fill the background with black
        
        # Background of Menu system
        self.engine.screen.blit(self.menu_background_border, self.menu_background_border_rect)
        self.engine.screen.blit(self.menu_background_inner, self.menu_background_inner_rect)
        
        center_y = ( self.engine.height / 2.0 ) - ( len(self.menus[self.menu_set]['List']) / 2.0 * 50 )
        shadow_offset = 2
        
        # Print the Title
        text = self.engine.font.render( self.menus[self.menu_set]['Title'], 0, (255, 0, 0))
        text_shadow = self.engine.font.render( self.menus[self.menu_set]['Title'], 0, (0, 0, 0))
        self.engine.screen.blit( text_shadow, ( ( self.engine.width / 2.0 ) - ( text.get_size()[0] / 2.0 ) + shadow_offset, 70 + shadow_offset ) )
        self.engine.screen.blit( text, ( ( self.engine.width / 2.0 ) - ( text.get_size()[0] / 2.0 ), 70 ) )
        
        for button in self.menus[self.menu_set]['List']:
            high_light = (255, 255, 255)
            
            if self.currently_selected == button:
                high_light = (255, 100, 100)
            
            if self.menu_set in ['in_game_controls', 'main_menu_controls'] and button != 'Back':
                if button == "Up":
                    name = self.engine.control_move_north
                    
                elif button == "Down":
                    name = self.engine.control_move_south
                    
                elif button == "Left":
                    name = self.engine.control_move_west
                    
                elif button == "Right":
                    name = self.engine.control_move_east
                    
                elif button == "Use/Pickup":
                    name = self.engine.control_use
                    
                elif button == "Fire":
                    name = self.engine.control_shoot
                    
                elif button == "Open Tech Tree":
                    name = self.engine.control_tech_tree
                
                button = "%s: %s" % (button, pygame.key.name(name) )
            
            if self.menu_set in ['in_game_options', 'main_menu_options']:
                if ( button == "Music" and self.engine.music_volumn ) or ( button == "Sound" and self.engine.sound_volumn ):
                    button = "%s: %s" % ( button, "On" )
                    
                elif ( button == "Music" and not self.engine.music_volumn ) or ( button == "Sound" and not self.engine.sound_volumn ):
                    button = "%s: %s" % ( button, "Off" )
            
            text = self.engine.font.render( button, 0, high_light )
            text_shadow = self.engine.font.render( button, 0, (0, 0, 0) )
            
            center_x = ( self.engine.width / 2.0 ) - ( text.get_size()[0] / 2.0 )
            
            self.engine.screen.blit( text_shadow, ( center_x + shadow_offset, center_y + shadow_offset ) )
            self.engine.screen.blit( text, ( center_x, center_y ) )
            
            center_y += 50 # only adjust the next y after the rendering
        
        pygame.display.flip()
    
    def OnEvent(self, events):
        for event in events:
            if event.type == pygame.QUIT:
                self.engine.Quit()
            
            self.HandleEvent(event)
    
    def HandleEvent(self, event):
        if event.type in []:
            return # Ignore these events for now
        
        pressed = pygame.mouse.get_pressed()
        
        if ( event.type == pygame.MOUSEBUTTONDOWN ) and ( pressed == (1, 0, 0) ):
            # Button 1
            
            return # Do not continue

        if ( event.type == pygame.MOUSEBUTTONDOWN ) and ( pressed == (0, 0, 1) ):
            # Button 2
            
            return # Do not continue
        
        if ( event.type == pygame.KEYDOWN ):
            self.handleKeyPressedEvents( event.key )
            
            return # Do not continue
        
        if ( event.type == pygame.KEYUP ):
            #self.handleKeyReleasedEvents( event.key )
            
            return # Do not continue
        
        if ( event.type == CustomEvents.quit_game ):
            self.Alive = False
            
            self.engine.SendEvent( CustomEvents.quit_game )
            
            return
        
        if ( event.type == CustomEvents.new_game ):
            self.Alive = False
            
            self.engine.SendEvent( CustomEvents.new_game )
            
            return
    
    def handleKeyPressedEvents( self, key ):
        if key == pygame.K_ESCAPE and self.menu_set.startswith("in_game"):
            self.Alive = False
            
            return
        
        if self.entered_tech_tree and key == self.engine.control_tech_tree:
            # Close the tech menu because we know we're here
            self.Alive = False
            
            return
        
        if key in [pygame.K_UP, self.engine.control_move_north]:
            self.SelectPrevious()
            
            return
        
        if key in [pygame.K_DOWN, self.engine.control_move_south]:
            self.SelectNext()
            
            return
        
        if key in [pygame.K_RETURN, self.engine.control_use]:
            self.SelectCurrent()
            
            return
    
    def ChangeMenu(self, menu_set):
        # Change to the new menu set
        self.currently_selected = self.menus[menu_set]['List'][0] # The first element should be selected by default
        self.menu_set = menu_set
    
    def SelectPrevious(self):
        menu_list = self.menus[self.menu_set]['List']
        index = menu_list.index(self.currently_selected)
        
        if index - 1 < 0:
            self.currently_selected = menu_list[-1] # previous value
        else:
            self.currently_selected = menu_list[index - 1] # previous value
    
    def SelectNext(self):
        menu_list = self.menus[self.menu_set]['List']
        index = menu_list.index(self.currently_selected)
        
        if index + 1 > len( menu_list ) - 1:
            self.currently_selected = menu_list[0] # next value
        else:
            self.currently_selected = menu_list[index + 1] # next value
    
    def SelectCurrent(self):
        # Run the information for that menu set
        method = self.menus[self.menu_set][self.currently_selected]['method']
        value = self.menus[self.menu_set][self.currently_selected]['value']
        if value:
            method( value )
        else:
            method()
    